﻿// ===============================================================================
// XmlConfigurationTest.cs
// EOS Framework
// ===============================================================================
// Copyright (c) EOS Development Group. All rights reserved.
// ===============================================================================

namespace EOS.Framework.Configuration.Tests
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using EOS.Framework.Contracts.Configuration;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    /// <summary>
    /// This is a test class for XmlConfigurationTest and is intended
    /// to contain all XmlConfigurationTest Unit Tests
    /// </summary>
    [TestClass()]
    public class XmlConfigurationTest
    {
        private TestContext testContextInstance;
        private XmlConfiguration configuration;
        private const string workingFile = @"..\..\..\EOS.Framework.Configuration.Tests\TempConfig.xml";

        /// <summary>
        /// Gets or sets the test context which provides
        /// information about and functionality for the current test run.
        /// </summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        /// <summary>
        /// Initializes the test.
        /// </summary>
        [TestInitialize]
        public void TestInitialize()
        {
            if (File.Exists(workingFile))
            {
                File.Delete(workingFile);
            }
            File.Copy(@"..\..\..\EOS.Framework.Configuration.Tests\TestConfig.xml", workingFile);

            configuration = new XmlConfiguration();
            configuration.Load(workingFile);
        }

        /// <summary>
        /// Cleans up the test.
        /// </summary>
        [TestCleanup]
        public void TestCleanUp()
        {
            File.Delete(workingFile);
        }

        /// <summary>
        /// A test for SetValueList. List cannot be null.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentNullException))]
        public void SetValueListNullListExceptionTest()
        {
            configuration.SetValueList<int>("Path", null);
        }

        /// <summary>
        /// A test for SetValueList. Path cannot be null.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentNullException))]
        public void SetValueListNullPathExceptionTest()
        {
            configuration.SetValueList<int>(null, new List<int>());
        }

        /// <summary>
        /// A test for SetValueList. Path cannot be empty.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentException))]
        public void SetValueListEmptyPathExceptionTest()
        {
            configuration.SetValueList<int>(string.Empty, new List<int>());
        }

        /// <summary>
        /// A test for SetValueList. Path cannot contains only blanks.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentException))]
        public void SetValueListBlanksOnlyPathExceptionTest()
        {
            configuration.SetValueList<int>(" ", new List<int>());
        }

        /// <summary>
        /// A generic test for SetValueList
        ///</summary>
        public void SetValueListTestHelper<T>(string path, List<T> values)
        {
            configuration.SetValueList<T>(path, values);

            List<T> readValues = configuration.GetValueList<T>(path);
            Assert.AreEqual(readValues.Count, values.Count, "Nicht alle oder mehr Elemente wurden gespeichert");

            for (int i = 0; i < values.Count; i++)
            {
                Assert.AreEqual(readValues[i], values[i], "Werte wurden nicht korrekt gespeichert");
            }
        }

        /// <summary>
        /// A test for SetValueList
        ///</summary>
        [TestMethod()]
        public void SetValueListTest()
        {
            List<string> strings = new List<string>();
            strings.Add("Hello");
            strings.Add("World");

            SetValueListTestHelper<string>("WriteSimpleList", strings);

            List<Mockups.StoredClass> storedClasses = new List<Mockups.StoredClass>();
            storedClasses.Add(new Mockups.StoredClass(1, "Hello"));
            storedClasses.Add(new Mockups.StoredClass(2, "World"));

            SetValueListTestHelper<Mockups.StoredClass>("WriteClassList", storedClasses);
        }

        /// <summary>
        /// A test for SetValue. Value cannot be null.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentNullException))]
        public void SetValueNullValueExceptionTest()
        {
            configuration.SetValue<Mockups.StoredClass>("Path", null);
        }

        /// <summary>
        /// A test for SetValue. Path cannot be null.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentNullException))]
        public void SetValueNullPathExceptionTest()
        {
            configuration.SetValue<int>(null, 123);
        }

        /// <summary>
        /// A test for SetValue. Path cannot be empty.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentException))]
        public void SetValueEmptyPathExceptionTest()
        {
            configuration.SetValue<int>(string.Empty, 123);
        }

        /// <summary>
        /// A test for SetValue. Path cannot contains only blanks.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentException))]
        public void SetValueBlanksOnlyPathExceptionTest()
        {
            configuration.SetValue<int>(" ", 123);
        }

        /// <summary>
        /// A generic test for SetValue
        ///</summary>
        public void SetValueTestHelper<T>(string path, T value)
        {
            configuration.SetValue<T>(path, value);

            T readValue = configuration.GetValue<T>(path);
            Assert.AreEqual(value, readValue);
        }

        /// <summary>
        /// A test for SetValue.
        /// </summary>
        [TestMethod()]
        public void SetValueTest()
        {
            SetValueTestHelper<int>("WriteInt", 123);
            SetValueTestHelper<Mockups.StoredClass>("WriteStoredClass", new Mockups.StoredClass(123, "Hello World"));
        }

        /// <summary>
        /// A test for GetValueList. Path cannot be null.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentNullException))]
        public void GetValueListNullPathExceptionTest()
        {
            configuration.GetValueList<int>(null);
        }

        /// <summary>
        /// A test for SetValueList. Path cannot be empty.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentException))]
        public void GetValueListEmptyPathExceptionTest()
        {
            configuration.GetValueList<int>(string.Empty);
        }

        /// <summary>
        /// A test for GetValueList. Path cannot contains only blanks.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentException))]
        public void GetValueListBlanksOnlyPathExceptionTest()
        {
            configuration.GetValueList<int>(" ");
        }

        /// <summary>
        /// A generic test for GetValueList.
        /// </summary>
        public void GetValueListTestHelper<T>(string path, List<T> expected)
        {
            List<T> actual = configuration.GetValueList<T>(path);

            Assert.AreEqual(actual.Count, expected.Count, "List hat nicht die richtige Anzahl an Elementen");

            for (int i = 0; i < expected.Count; i++)
            {
                Assert.AreEqual(expected[i], actual[i]);
            }
        }

        /// <summary>
        /// A test for GetValueList.
        /// </summary>
        [TestMethod()]
        public void GetValueListTest()
        {
            List<string> strings = new List<string>();
            strings.Add("Hello");
            strings.Add("World");

            GetValueListTestHelper<string>("SimpleList", strings);

            List<Mockups.StoredClass> storedClasses = new List<Mockups.StoredClass>();
            storedClasses.Add(new Mockups.StoredClass(1, "Hello"));
            storedClasses.Add(new Mockups.StoredClass(2, "World"));

            GetValueListTestHelper<Mockups.StoredClass>("ClassList", storedClasses);
        }

        /// <summary>
        /// A test for GetValue. Path cannot be null.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentNullException))]
        public void GetValueNullPathExceptionTest()
        {
            configuration.GetValue<int>(null);
        }

        /// <summary>
        /// A test for GetValue. Path cannot be empty.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentException))]
        public void GetValueEmptyPathExceptionTest()
        {
            configuration.GetValue<int>(string.Empty);
        }

        /// <summary>
        /// A test for GetValue. Path cannot contains only blanks.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentException))]
        public void GetValueBlanksOnlyPathExceptionTest()
        {
            configuration.GetValue<int>(" ");
        }

        /// <summary>
        /// A generic test for GetValue
        ///</summary>
        public void GetValueTestHelper<T>(string path, T expected)
        {
            T actual = configuration.GetValue<T>(path);
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        /// A test for GetValue
        ///</summary>
        [TestMethod()]
        public void GetValueTest()
        {
            GetValueTestHelper<int>("Foo", 123);
            GetValueTestHelper<Mockups.StoredClass>("Bar", new Mockups.StoredClass(123, "Test"));
        }

        /// <summary>
        /// A test for GetValue. Xml structure for a value type must exist.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ParsingConfigFileException))]
        public void GetValueValueTypeNotFoundExceptionTest()
        {
            configuration.GetValue<int>("Broken");
        }        
        
        /// <summary>
        /// A test for GetValue. Xml structure for a reference type must exist.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ParsingConfigFileException))]
        public void GetValueReferenceTypeNotFoundExceptionTest()
        {
            configuration.GetValue<Mockups.StoredClass>("BrokenClass");
        }

        /// <summary>
        /// A test for AddValue. Value cannot be null.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentNullException))]
        public void AddValueNullValueExceptionTest()
        {
            configuration.AddValue<Mockups.StoredClass>("Path", null);
        }

        /// <summary>
        /// A test for AddValue. Path cannot be null.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentNullException))]
        public void AddValueNullPathExceptionTest()
        {
            configuration.AddValue<int>(null, 123);
        }

        /// <summary>
        /// A test for AddValue. Path cannot be empty.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentException))]
        public void AddValueEmptyPathExceptionTest()
        {
            configuration.AddValue<int>(string.Empty, 123);
        }

        /// <summary>
        /// A test for AddValue. Path cannot contains only blanks.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentException))]
        public void AddValueBlanksOnlyPathExceptionTest()
        {
            configuration.AddValue<int>(" ", 123);
        }

        /// <summary>
        /// A test for AddValue. Value cannot be a collection.
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentException))]
        public void AddValueCollectionValueExceptionTest()
        {
            configuration.AddValue<List<int>>("Path", new List<int>());
        }

        /// <summary>
        /// A generic test for AddValue.
        /// </summary>
        public void AddValueTestHelper<T>(string path, List<T> values, T newValue)
        {
            configuration.AddValue<T>(path, newValue);

            List<T> readValues = configuration.GetValueList<T>(path);
            Assert.AreEqual(readValues.Count, values.Count, "Neues element wurde nicht korrekt geseichert");

            for (int i = 0; i < values.Count; i++)
            {
                Assert.AreEqual(readValues[i], values[i], "Werte wurden nicht korrekt gespeichert");
            }
        }

        /// <summary>
        /// A test for AddValue
        /// </summary>
        [TestMethod()]
        public void AddValueTest()
        {
            List<string> strings = new List<string>();
            strings.Add("Hello");
            strings.Add("World");
            strings.Add("!");

            AddValueTestHelper<string>("SimpleList", strings, "!");

            List<Mockups.StoredClass> storedClasses = new List<Mockups.StoredClass>();
            storedClasses.Add(new Mockups.StoredClass(1, "Hello"));
            storedClasses.Add(new Mockups.StoredClass(2, "World"));
            storedClasses.Add(new Mockups.StoredClass(3, "!"));

            AddValueTestHelper<Mockups.StoredClass>("ClassList", storedClasses, new Mockups.StoredClass(3, "!"));
        }
    }
}
